<?php

/**
 * 获得当前格林威治时间的时间戳
 *
 * @return  integer
 */
function gmtime()
{
  return $GLOBALS['timezone'] ? time() - date('Z') : time();
}
/**
 * 获得服务器的时区
 *
 * @return  integer
 */
function server_timezone()
{
  return function_exists('date_default_timezone_get') ? date_default_timezone_get() : date('Z') / 3600;
}
/**
 *  生成一个用户自定义时区日期的GMT时间戳
 *
 * @access  public
 * @param   int   $hour
 * @param   int   $minute
 * @param   int   $second
 * @param   int   $month
 * @param   int   $day
 * @param   int   $year
 *
 * @return void
 */
function local_mktime($hour = NULL, $minute = NULL, $second = NULL, $month = NULL, $day = NULL, $year = NULL)
{
  $timezone = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $GLOBALS['timezone'];
  /**
   * $time = mktime($hour, $minute, $second, $month, $day, $year) - date('Z') + (date('Z') - $timezone * 3600)
   * 先用mktime生成时间戳，再减去date('Z')转换为GMT时间，然后修正为用户自定义时间。以下是化简后结果
   **/
  return mktime($hour, $minute, $second, $month, $day, $year) - $timezone * 3600;
}
/**
 * 将GMT时间戳格式化为用户自定义时区日期
 *
 * @param  string     $format
 * @param  integer    $time     该参数必须是一个GMT的时间戳
 *
 * @return  string
 */
function local_date($format = 'Y-m-d H:i:s', $time = NULL)
{
  $timezone = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $GLOBALS['timezone'];

  if (empty($format)) {
    $format = 'Y-m-d H:i:s';
  }

  if ($time === NULL) {
    $time = gmtime();
  }

  if ($time <= 0) {
    return '';
  }

  $time += $timezone * 3600;
  return date($format, $time);
}
/**
 * 转换字符串形式的时间表达式为GMT时间戳
 *
 * @param   string  $str
 *
 * @return  integer
 */
function gmstr2time($str)
{
  $time = strtotime($str);
  if ($time > 0) {
    $time -= date('Z');
  }
  return $time;
}
/**
 *  将一个用户自定义时区的日期转为GMT时间戳
 *
 * @access  public
 * @param   string    $str
 *
 * @return  integer
 */
function local_strtotime($str)
{
  $timezone = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $GLOBALS['timezone'];
  /**
   * $time = mktime($hour, $minute, $second, $month, $day, $year) - date('Z') + (date('Z') - $timezone * 3600)
   * 先用mktime生成时间戳，再减去date('Z')转换为GMT时间，然后修正为用户自定义时间。以下是化简后结果
   **/
  return strtotime($str) - $timezone * 3600;
}
/**
 * 获得用户所在时区指定的时间戳
 *
 * @param   $timestamp  integer   该时间戳必须是一个服务器本地的时间戳
 *
 * @return  array
 */
function local_gettime($timestamp = NULL)
{
  $tmp = local_getdate($timestamp);
  return $tmp[0];
}
/**
 * 获得用户所在时区指定的日期和时间信息
 *
 * @param   $timestamp  integer   该时间戳必须是一个服务器本地的时间戳
 *
 * @return  array
 */
function local_getdate($timestamp = NULL)
{
  $timezone = isset($_SESSION['timezone']) ? $_SESSION['timezone'] : $GLOBALS['timezone'];
  /* 如果时间戳为空，则获得服务器的当前时间 */
  if ($timestamp === NULL) {
    $timestamp = time();
  }
  $gmt = $timestamp - date('Z');
  // 得到该时间的格林威治时间
  $local_time = $gmt + $timezone * 3600;
  // 转换为用户所在时区的时间戳
  return getdate($local_time);
}
/**
 * getDateDiff
 *
 * @param [type] $sday
 * @param [type] $eday
 * @param string $unit
 * @return int
 */
function getDateDiff($sday, $eday, $unit = 'd')
{
  switch ($unit) {
    case 'y':
      $retval = local_date('Y', $eday) - local_date('Y', $sday);
      break;
    case 'm':
      $retval = local_date('m', $eday) - local_date('m', $sday);
      break;
    case 'w':
      $retval = local_date('W', $eday) - local_date('W', $sday);
      break;
    case 'd':
      $retval = local_date('d', $eday) - local_date('d', $sday);
      break;
    case 'h':
      $retval = local_date('H', $eday) - local_date('H', $sday);
      break;
    case 'i':
      $retval = local_date('i', $eday) - local_date('i', $sday);
      break;
    case 's':
      $retval = local_date('s', $eday) - local_date('s', $sday);
      break;
    default:
      break;
  }
  return intval($retval);
}
/**
 * getTimeDiff
 * 通过起始和结束的日期获得天数
 * 已实际时间比对，并非判断当天当；比如从昨天的10点整倒今天的10点整
 * @param   $timestamp  integer   该时间戳必须是一个服务器本地的时间戳
 *
 * @return  int
 */
function getTimeDiff($sday, $eday, $unit = 'd')
{
  $diff = $eday - $sday;
  switch ($unit) {
    case 'y':
      $retval = bcdiv($diff, 60 * 60 * 24 * 365, 1);
      break;
    case 'm':
      $retval = bcdiv($diff, 60 * 60 * 24 * 30, 1);
      break;
    case 'w':
      $retval = bcdiv($diff, 60 * 60 * 24 * 7, 1);
      break;
    case 'd':
      $retval = bcdiv($diff, 60 * 60 * 24, 1);
      break;
    case 'h':
      $retval = bcdiv($diff, 60 * 60, 1);
      break;
    case 'i':
      $retval = bcdiv($diff, 60, 1);
      break;
    case 's':
      $retval = $diff;
      break;
    default:
      break;
  }
  return intval($retval);
}
// 通过起始日期获取结束日期
// $sday 起始时间
// $days 间隔天数
// $case 0 返回格林威治时间;1 返回时间格式
function getEndDate($sday, $days, $case = 0)
{
  $stime = date('Y-m-d H:i:s', $sday);
  $sarr = explode(' ', $stime);
  if (!empty($sarr)) {
    $symd = explode('-', $sarr[0]);
    $shis = explode(':', $sarr[1]);
    switch ($case) {
      case 0:
        $eday = local_mktime($shis[0], $shis[1], $shis[2], $symd[1], $symd[2] + $days, $symd[0]);
        break;
      case 1:
        $eday = local_date('Y-m-d H:i:s', mktime($shis[0], $shis[1], $shis[2], $symd[1], $symd[2] + $days, $symd[0]));
        break;
      default:
        break;
    }
    return $eday;
  }

  return '时间格式有问题';
}
// 计算分期天数的函数
function getPeriodDays($d, $p)
{
  $pd = @ceil($d / $p);
  $epd = $d - ($p - 1) * $pd;
  for ($i = 0; $i < $p; $i++) {
    if ($i == $p - 1) {
      $res[$i]['days'] = $epd;
      continue;
    }

    $res[$i]['days'] = $pd;
  }
  return $res;
}
// 毫秒级时间
function microtime_float($int = 1)
{
  list($msec, $sec) = explode(' ', microtime());

  return $int == 1
    ? ((float)$msec + (float)$sec) * 10000
    : ((float)$msec + (float)$sec);
}
// 时间转16进制（无重复字串标识）
function time_hex($mt = 0)
{
  $float = !empty($mt) ? $mt : microtime_float();

  return dechex(10000 * $float);
}
//这个星期的星期一
// @$timestamp ，某个星期的某一个时间戳，默认为当前时间
// @is_return_timestamp ,是否返回时间戳，否则返回时间格式
function this_monday($timestamp = 0, $is_return_timestamp = true)
{
  $timestamp = $timestamp == 0 ? gmtime() : $timestamp;
  $monday_date = date('Y-m-d', $timestamp - 86400 * date('w', $timestamp) + (date('w', $timestamp) > 0 ? 86400 : -518400)); //6*86400
  if ($is_return_timestamp) {
    return local_strtotime($monday_date);
  }
  return $monday_date;
}
function this_sunday($timestamp = 0, $is_return_timestamp = true)
{
  $timestamp = $timestamp == 0 ? gmtime() : $timestamp;
  $sunday = this_monday($timestamp) + 518400;

  return $is_return_timestamp ? $sunday : date('Y-m-d', $sunday);
}

/*PHP获取当前日期是第几周和本周开始日期和本周结束日期*/
function get_date_info($_timestamp = 0)
{
  if ($_timestamp == 0) $_timestamp = gmtime();
  $res = array();
  //$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
  $res['year'] = local_date('Y', $_timestamp);
  $res['year_start'] = local_date($res['year'] . '-01-01');
  $res['year_end'] = local_strtotime($res['year_start'] . " +1 year");
  $res['year_start'] = local_strtotime($res['year_start']);
  $res['month'] = local_date('m', $_timestamp);
  $res['month_start'] = local_date($res['year'] . '-' . $res['month'] . '-01');
  $res['month_end'] = local_strtotime(local_date('Y-m-01', local_strtotime($res['month_start'] . " +1 month")));
  $res['month_start'] = local_strtotime($res['month_start']);
  $first = 1;
  $now = local_date('Y-m-d', $_timestamp);
  //当日在整年中的第几周
  $res['week'] = local_date('W', $_timestamp);
  //获取当前周的第几天 周日是 0 周一到周六是 1 - 6
  $w = local_date('w', $_timestamp);
  //获取本周开始日期，如果$w是0，则表示周日，减去 6 天
  // $week_start = local_date('Y-m-d', local_strtotime("$now -" . ($w ? $w - $first : 6) . ' days'));
  $res['week_start'] = local_strtotime("$now -" . ($w ? $w - $first : 6) . ' days');
  // $res['week_start'] = $week_start;
  //本周结束日期
  // $week_end = local_date('Y-m-d', local_strtotime("$week_start +6 days"));
  $res['week_end'] = local_strtotime(local_date('Y-m-d', $res['week_start']) . " +6 days");
  // $res['week_end'] = $week_end;
  // $res['week_end_plus'] = local_date('Y-m-d', local_strtotime("$week_start +7 days"));
  $res['week_end_plus'] = local_strtotime(local_date('Y-m-d', $res['week_start']) . " +7 days");
  return $res;
}

/**
 * date_GDSE
 * @param mixed $date 'Y-m-d H:i:s'
 * @return false|void
 */
function date_GDSE($date_str = '')
{
  if (empty($date_str)) {
    $date_str = local_date('Y-m-d H:i:s');
  }

  $res = array();

  list($date_part, $time_part) = explode(' ', $date_str);
  unset($time_part);
  list($res['y'], $res['m'], $res['d']) = explode('-', $date_part);
  unset($time_part);

  return $res;
}
/**
 * time_GDSE
 * @param mixed $time gmtime()/time()
 * @return false|array
 */
function timestamp_GDSE($timestamp = '')
{
  if (empty($timestamp)) {
    $timestamp = gmtime();
  }

  $res = array();
  $res['y'] = local_date('Y', $timestamp);
  $res['m'] = local_date('m', $timestamp);
  $res['d'] = local_date('d', $timestamp);

  return $res;
}

/**
 * get_date_start_end
 * @param array $date ["d"=>'',"m"=>'',"y"=>'']
 * 参数格式可以通过上面的函数转换获得
 * @param string $type d:day,w:week,m:month,y:year'
 * @return array
 */
function get_date_start_end($date = [], $type = 'd')
{
  $res = array();

  if (empty($date)) {
    $date['y'] = local_date('Y');
    $date['m'] = local_date('m');
    $date['d'] = local_date('d');
  }

  switch ($type) {
    case 'y':
      $res['start'] = local_mktime(0, 0, 0, 1, 1, $date['y']);
      $res['end'] = local_mktime(0, 0, 0, 1, 1, $date['y'] + 1);
      break;
    case 'm':
      $res['start'] = local_mktime(0, 0, 0, $date['m'], 1, $date['y']);
      $res['end'] = local_mktime(0, 0, 0, $date['m'] + 1, 1, $date['y']);
      break;
    case 'd':
    default:
      $res['start'] = local_mktime(0, 0, 0, $date['m'], $date['d'], $date['y']);
      $res['end'] = local_mktime(0, 0, 0, $date['m'], $date['d'] + 1, $date['y']);
      break;
  }

  return $res;
  /*
  if ($type == 'w') {
    $res['w']['start'] = mktime(0, 0, 0, date('m'), date('d') - date('N') + 1 - $date, date('Y'));
    $res['w']['end'] = mktime(0, 0, 0, date('m'), date('d') - date('N') + 7 - $date, date('Y'));
  } elseif ($type == 'm') {
    $res['m']['start'] = mktime(0, 0, 0, date('m') - $date, 1, date('Y'));
    $res['m']['end'] = mktime(0, 0, 0, date('m') + 1 - $date, 1, date('Y'));
  } elseif ($type == 'y') {
    $res['y']['start'] = mktime(0, 0, 0, 1, 1, date('Y') - $date);
    $res['y']['end'] = mktime(0, 0, 0, 1, 1, date('Y') + 1 - $date);
  } else {
    $res['d']['start'] = local_mktime(0, 0, 0, date('m'), date('d') - $date, date('Y'));
    $res['d']['end'] = local_mktime(0, 0, 0, date('m'), date('d') + 1 - $date, date('Y'));
  }
  */
}

/**
 * get_date_period
 * @param int $period
 * @param string $type
 * @return false|array 返回二维数组,单数值注意调用$array[0]['start'],$array[0]['end']
 */
function get_date_period($period = 0, $type = 'd')
{
  if (empty($period)) return false;

  $res = array();
  $date_current = timestamp_GDSE();

  if ($type == 'y') {
    for ($i = 0; $i < $period; $i++) {
      $res[] = get_date_start_end($date_current, 'y');
      $date_current['y'] -= 1;
    }
  } elseif ($type == 'm') {
    for ($i = 0; $i < $period; $i++) {
      $res[] = get_date_start_end($date_current, 'm');
      $date_current['m'] -= 1;
    }
  } elseif ($type == 'd') {
    for ($i = 0; $i < $period; $i++) {
      $res[] = get_date_start_end($date_current, 'd');
      $date_current['d'] -= 1;
    }
  }

  return array_reverse($res);
}